package net.tv90.bfmccore.battlepass;

import net.tv90.bfmccore.battlepack.EnumBattlepackLevel;
import net.tv90.bfmccore.constant.RewardConstant;
import net.tv90.bfmccore.event.PlayerBattlepassUpgradedEvent;
import net.tv90.bfmccore.task.DailyTask;
import net.tv90.bfmccore.task.WeeklyTask;
import org.bitterorange.flansmodslain.actions.Money;
import org.bitterorange.flansmodslain.actions.Point;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import java.io.*;
import java.nio.file.Files;
import java.time.DayOfWeek;
import java.util.HashMap;
import java.util.Map;

import static net.tv90.bfmccore.BFMCCore.PLUGIN_ROOT;
import static net.tv90.bfmccore.battlepack.Battlepack.getBattlepack;

public class Battlepass {

    /**
     * 通行证最大等级
     */
    public static final int MAX_LEVEL = 100;

    /**
     * 当前通行证名称
     */
    public static final String CURRENT_BATTLE_PASS_NAME = "s2";

    /**
     * 升级通行证所需点数
     */
    public static final int POINT_TO_UPGRADE = 10000;

    /**
     * 购买通行证所需游戏币
     */
    public static final int MONEY_TO_BUY_BATTLEPASS = 5000;

    /**
     * 每挂机半小时获得的点数
     */
    public static final int POINT_PER_HALF_HOUR = 2000;

    /**
     * 是否启用每日点数限制
     */
    public static boolean enableDailyPointLimit = true;

    /**
     * 每日点数上限
     */
    public static final int DAILY_POINT_LIMIT = 75000;

    /**
     * 玩家通行证数据
     */
    public static volatile Map<String, BattlepassPoint> playerBattlepassData = new HashMap<>();

    /**
     * 玩家每日点数
     */
    public static volatile Map<String, Integer> playerDailyPoint = new HashMap<>();

    static {
        initBattlepassData();
        new BattlepassPapiShow().register();
        if (enableDailyPointLimit) {
            initDailyLimitData();

            new ClearDailyLimitTask(7, 0, 0);
        }

        new DoublePointTask(DayOfWeek.FRIDAY, 19, 0, 0);
        new DoublePointTask(DayOfWeek.SATURDAY, 19, 0, 0);
        new DoublePointTask(DayOfWeek.SUNDAY, 19, 0, 0);

        new DoublePointEndTask(DayOfWeek.FRIDAY, 23, 59, 59);
        new DoublePointEndTask(DayOfWeek.SATURDAY, 23, 59, 59);
        new DoublePointEndTask(DayOfWeek.SUNDAY, 23, 59, 59);
    }

    /**
     * 从yaml文件中读取玩家的通行证数据
     */
    public static void initBattlepassData() {
        File file = new File(PLUGIN_ROOT, "/battlepass.dat");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            try (
                    InputStream inputStream = Files.newInputStream(file.toPath());
                    ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)
            ) {
                Object object = objectInputStream.readObject();
                playerBattlepassData = (object == null) ? new HashMap<>() : (Map<String, BattlepassPoint>) object;
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将玩家的通行证数据存入yaml文件
     */
    public static synchronized void storeBattlepassData() {
        File file = new File(PLUGIN_ROOT, "/battlepass.dat");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (
                OutputStream outputStream = Files.newOutputStream(file.toPath());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)
        ) {
            objectOutputStream.writeObject(playerBattlepassData);
            System.out.println("序列化玩家所储存通行证数据成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从yaml文件中读取玩家的通行证数据
     */
    public static void initDailyLimitData() {
        File file = new File(PLUGIN_ROOT, "/battlepassDailyLimit.dat");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            try (
                    InputStream inputStream = Files.newInputStream(file.toPath());
                    ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)
            ) {
                Object object = objectInputStream.readObject();
                playerDailyPoint = (object == null) ? new HashMap<>() : (Map<String, Integer>) object;
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将玩家的通行证数据存入yaml文件
     */
    public static synchronized void storeDailyLimitData() {
        File file = new File(PLUGIN_ROOT, "/battlepassDailyLimit.dat");
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (
                OutputStream outputStream = Files.newOutputStream(file.toPath());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)
        ) {
            objectOutputStream.writeObject(playerDailyPoint);
            System.out.println("序列化玩家通行证每日上限数据成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void addBattlepassPoint(Player player, int point) {
        if (player == null) {
            return;
        }

        if(enableDailyPointLimit) {
            int dailyPoint = playerDailyPoint.getOrDefault(player.getName(), 0);
            if (dailyPoint >= DAILY_POINT_LIMIT) {
                return;
            }
            playerDailyPoint.put(player.getName(), dailyPoint + point);
        }

        BattlepassPoint battlepassPoint = playerBattlepassData.get(player.getName());
        if (battlepassPoint == null) {
            battlepassPoint = new BattlepassPoint();
            battlepassPoint.setPoint(point);
            battlepassPoint.setLevel(1);
            playerBattlepassData.put(player.getName(), battlepassPoint);
        } else {
            int prevPoint = battlepassPoint.getPoint();
            int nextPoint = prevPoint + point;
            battlepassPoint.setPoint(nextPoint);
            for (int i = 1; i <= MAX_LEVEL; i++) {
                if (prevPoint < POINT_TO_UPGRADE * (i - 1) && nextPoint >= POINT_TO_UPGRADE * (i - 1)) {
                    battlepassPoint.setLevel(i);
                    //触发事件
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerBattlepassUpgradedEvent(player, i, nextPoint));
                    break;
                }
            }
        }
    }


    public static void buyBattlepass(Player player) {
        if (player == null) {
            return;
        }
        String battlepassName = CURRENT_BATTLE_PASS_NAME;
        if (player.hasPermission("bfmc.bps.buy." + battlepassName)) {
            player.sendMessage("§e[战斗通行证]你已经购买了" + battlepassName.toUpperCase() + "赛季战斗通行证");
            return;
        }
        if (Money.balanceOf(player) >= MONEY_TO_BUY_BATTLEPASS) {
            Money.take(player, MONEY_TO_BUY_BATTLEPASS);
            player.sendMessage("§e[战斗通行证]购买" + battlepassName.toUpperCase() + "赛季战斗通行证成功");
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + player.getName() +
                    " permission set bfmc.bps.buy." + battlepassName);
        } else {
            player.sendMessage("§e[战斗通行证]你的余额不足，需要" + MONEY_TO_BUY_BATTLEPASS + "游戏币购买" + battlepassName.toUpperCase() + "赛季战斗通行证，当前余额为" + Money.balanceOf(player));
        }
    }

    public static void queryBattlepass(Player sender) {
        if (sender == null) {
            return;
        }
        BattlepassPoint battlepassPoint = playerBattlepassData.get(sender.getName());
        if (battlepassPoint != null) {
            sender.sendMessage("§e[战斗通行证]你当前的战斗通行证等级为" + battlepassPoint.getLevel() + "级，当前总经验值为" + battlepassPoint.getPoint() + "，距离下一级还需"
                    + (POINT_TO_UPGRADE * battlepassPoint.getLevel() - battlepassPoint.getPoint()) + "经验值。今日积分为 "
                    + playerDailyPoint.getOrDefault(sender.getName(), 0) + " （通行证积分将于每日7:00am刷新）");
        } else {
            sender.sendMessage("§e[战斗通行证]你当前的战斗通行证等级为1级，当前总经验值为0，距离下一级还需" + POINT_TO_UPGRADE + "经验值。今日积分为0（通行证积分将于每日7:00am刷新）");
        }
        if (enableDailyPointLimit && playerDailyPoint.getOrDefault(sender.getName(), 0) >= DAILY_POINT_LIMIT) {
            sender.sendMessage("§e[战斗通行证]你今天的通行证积分已经达到上限" + DAILY_POINT_LIMIT + "点，明天再来吧");
        }
    }

    public static String queryBattlepassStatistic(Player sender) {
        if (sender == null) {
            return "";
        }
        BattlepassPoint battlepassPoint = playerBattlepassData.get(sender.getName());
        StringBuilder sb = new StringBuilder();
        if (battlepassPoint != null) {
            sb.append(CURRENT_BATTLE_PASS_NAME.toUpperCase()).append("通行证等级：")
                    .append(battlepassPoint.getLevel())
                    .append(" (")
                    .append(playerDailyPoint.getOrDefault(sender.getName(), 0))
                    .append("/")
                    .append(battlepassPoint.getPoint())
                    .append(")");
        } else {
            sb.append(CURRENT_BATTLE_PASS_NAME.toUpperCase()).append("通行证等级：1 (0/0)");
        }
        return sb.toString();
    }

    public static void giveRewardPermission(Player player, int level, String permission) {
        if (!preGiveReward(player, level)) return;
        Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + player.getName() +
                " permission set " + permission);
        postGiveReward(player, level);
        System.out.println("玩家" + player.getName() + "领取了" + level + "级通行证的权限奖励");
    }

    public static void giveRewardRank(Player player, int level, int rank) {
        if (!preGiveReward(player, level)) return;
        Point.add(player, rank);
        player.sendMessage("§e[战斗通行证]你获得了" + rank + "点军衔");
        postGiveReward(player, level);
        System.out.println("玩家" + player.getName() + "领取了" + level + "级通行证的军衔奖励");
    }

    public static void giveRewardMoney(Player player, int level, int money) {
        if (!preGiveReward(player, level)) return;
        Money.give(player, money);
        player.sendMessage("§e[战斗通行证]你获得了" + money + "游戏币");
        postGiveReward(player, level);
        System.out.println("玩家" + player.getName() + "领取了" + level + "级通行证的游戏币奖励");
    }

    public static void giveRewardBattlepack(Player player, int level, String battlepackLevel) {
        if (!preGiveReward(player, level)) return;
        EnumBattlepackLevel enumBattlepackLevel = EnumBattlepackLevel.valueOf(battlepackLevel.toUpperCase());
        getBattlepack(player, enumBattlepackLevel);
        postGiveReward(player, level);
        System.out.println("玩家" + player.getName() + "领取了" + level + "级通行证的战斗包奖励");
    }

    private static void postGiveReward(Player player, int level) {
        Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + player.getName() +
                " permission set bfmc.bps.reward." + CURRENT_BATTLE_PASS_NAME + "." + level);
        Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "title " + player.getName() + " title 领取奖励成功");
        player.playSound(player.getLocation(), "custom.Awards_Unlock", 100, 1);
    }

    private static boolean preGiveReward(Player player, int level) {
        if(!player.hasPermission("bfmc.bps.buy." + CURRENT_BATTLE_PASS_NAME)) {
            player.sendMessage("§e[战斗通行证]你还未购买" + CURRENT_BATTLE_PASS_NAME.toUpperCase() +
                    "赛季战斗通行证，输入 §b/bps buy §e花费 §b" + MONEY_TO_BUY_BATTLEPASS + "§e 游戏币购买通行证即可获得丰厚奖励");
            return false;
        }
        if(!player.hasPermission("bfmc.bps." + CURRENT_BATTLE_PASS_NAME + "." + level)) {
            player.sendMessage("§e[战斗通行证]你还未达到该等级");
            return false;
        }
        if(player.hasPermission("bfmc.bps.reward." + CURRENT_BATTLE_PASS_NAME + "." + level)) {
            player.sendMessage("§e[战斗通行证]你已经领取过该等级的奖励了");
            return false;
        }
        return true;
    }

    public static void giveRewardPermissions(Player player, int level, String[] permissions) {
        if (!preGiveReward(player, level)) return;
        for (String permission : permissions) {
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "lp user " + player.getName() +
                    " permission set " + permission);
        }
        postGiveReward(player, level);
        System.out.println("玩家" + player.getName() + "领取了" + level + "级通行证的权限奖励");
    }


    static class ClearDailyLimitTask extends DailyTask {

        public ClearDailyLimitTask(int hour, int minute, int second) {
            super(hour, minute, second);
        }

        @Override
        public void schedule() {
            playerDailyPoint.clear();
            System.out.println("已经清除玩家每日点数上限");
            storeDailyLimitData();
        }
    }

    static class DoublePointTask extends WeeklyTask {

        public DoublePointTask(DayOfWeek dayOfWeek, int hour, int minute, int second) {
            super(dayOfWeek, hour, minute, second);
        }

        @Override
        public void schedule() {
            RewardConstant.POINT_MAGNIFICATION = 2;
            Bukkit.broadcastMessage("§e[管理员]本周通行证双倍积分活动已经开启");
        }
    }

    static class DoublePointEndTask extends WeeklyTask {

        public DoublePointEndTask(DayOfWeek dayOfWeek, int hour, int minute, int second) {
            super(dayOfWeek, hour, minute, second);
        }

        @Override
        public void schedule() {
            RewardConstant.POINT_MAGNIFICATION = 1;
            Bukkit.broadcastMessage("§e[管理员]本周通行证双倍积分活动已经结束");
        }
    }
}
